import { ClassName, Events, LinkMark, Shape } from "@/Constants";
import { IPixelPos } from "@/Interface";
import Feature from "../../Feature";
import { Utils } from "@/utils";
import ACtrlPnt from "./ACtrlPnt";
import Line from "@/features/basic-shape/Line";
import RCtrlPnt from "./RCtrlPnt";

function getPos(line: Line, linkMark = LinkMark.END) {
    if (line.pointArr.length > 0) {
        if (linkMark === LinkMark.END) {
            return line.pointArr[line.pointArr.length - 1]
        } else {
            return line.pointArr[0]
        }
    } else {
        return { x: 1, y: 1 }   // 不能0,0 ,否则屏幕外无法绘制
    }
}

function getAnglePos(line: Line, linkMark = LinkMark.END) {
    if (line.pointArr.length > 1) {
        if (linkMark === LinkMark.END) {
            return line.pointArr[line.pointArr.length - 2]
        } else {
            return line.pointArr[1]
        }
    } else {
        return { x: 1, y: 1 }
    }
}

export default class Arrow extends RCtrlPnt {

    linkMark = LinkMark.END;
    // _linkMark = LinkMark.END;
    // get linkMark() { return this._linkMark }
    // set linkMark(val) {
    //     this._linkMark = val;
    //     if (!this.parent || this.parent.endFeature == this) return;
    //     // this.pointArr[0] = getPos(this.parent as Line, this.linkMark);
    //     this.parent.setTarget(this, val)
    // }

    constructor(parent: Line, width = 1.5, height?:number) {
        super(parent, () => getPos(parent), width, height);
        this.getPoint = () => getPos(parent, this.linkMark)
        this.className = ClassName.ARROW;
        this.isStroke = true;
        this.shape = Shape.ARROW;
        this.fillStyle = parent.fillStyle;
        this.hoverStyle = parent.hoverStyle;
        this.focusStyle = parent.focusStyle;
        this.strokeStyle = parent.strokeStyle;
        this.lineWidth = parent.lineWidth;
        this.zIndex = parent.zIndex;
        this.isPixelLen = parent.isPixelLen;
        if (this.parent.className === ClassName.LINK) {
            this.on(Events.DRAG, () => {
                if (!this.parent || this.parent.endFeature == this) return;
                this.parent.setTarget(this, this.linkMark)
            })
            this.on(Events.DRAG_END, () => {
                const target = [...Feature.Gls.features].reverse().find(f => f.isPointIn && (f instanceof ACtrlPnt || Utils.isBasicFeature(f)) && f != this && f != this.parent);
                if (target) {
                    this.parent.setTarget(target, this.linkMark)
                } else {
                    this.parent.setTarget(this, this.linkMark)
                }
            })
        }
    }

    override draw(ctx: CanvasRenderingContext2D, pointArr: IPixelPos[], lineWidth: number, lineDashArr: number[]): void | Path2D {
        const center = pointArr[0]
        const width = Feature.Gls.getRatioSize(this.size.width, this.isPixelLen)
        const height = Feature.Gls.getRatioSize(this.size.height, this.isPixelLen)
        let path = new Path2D();   // 默认箭头形
        ctx.save()
        switch (this.shape) {
            case Shape.ARROW:
                path.moveTo(center.x, center.y + height / 2);
                path.lineTo(center.x - width, center.y + height);
                path.lineTo(center.x, center.y - height / 2);
                path.lineTo(center.x + width, center.y + height);
                break;
            default:
                path = this.getShape(path, center, width, height)
                break;
        }
        const anglePos = getAnglePos(this.parent as Line, this.linkMark);
        const pos = getPos(this.parent as Line, this.linkMark);
        if (anglePos) {
            const angle = Utils.getAngleOfTwoPnts(anglePos, pos);   // 获取两个点 水平方向上的角度
            this.rotateCtx(ctx, center, angle + 90);
        }
        this.setStyle(ctx, lineWidth, lineDashArr);
        this.isClosePath && path.closePath()
        this.isClosePath && ctx.fill(path);
        if (this.isStroke && this.lineWidth > 0) ctx.stroke(path);
        this.setPointIn(ctx, Utils.getRectPoints(center, { width, height }), path);
        this.updatePosByParent(this.parent, this.linkMark);
        ctx.restore()
        return path;
    }
}